API de Búsqueda de Contenido 1.0 de IIIF

Estado de este Documento

Esta Versión: 1.0.0

Última Versión Estable: 1.0.0

Editores

Copyright © 2015-2017 Editores y colaboradores. Publicado por IIIF Consortium bajo la licencia CC-BY, ver aviso legal.


Tabla de Contenidos

1. Introducción

En la API de Presentación de IIIF (pronunciado “Triple-I-Efe”), el contenido es presentado desde sistemas distribuídos mediante anotaciones (annotations). Ese contenido puede incluir imágenes (en muchos casos, con un servicio de la API de Imagen de IIIF como medio de acceso), audio, video, texto plano o enriquecido, o cualquier otra cosa. En un sistema vibrante y dinámico, ese contenido puede proceder de muchas fuentes, y ser rico, variado y abundante. Entre esos tipos de contenido, los recursos textuales son idóneos para la búsqueda, ya sean transcripciones, traducciones, o ediciones del contenido intelectual, o bien comentarios, descripciones, etiquetas, u otras anotaciones sobre el objeto.

Esta especificación define el mecanismo de interoperabilidad para realizar esas búsquedas en el contexto de IIIF. El ámbito de la especificación es la búsqueda de contenido de anotación en un recurso de IIIF, por ejemplo, Manifest, Range o Collection. Un objetivo fundamental es mantener la interacción tan coherente con los patrones existentes de IIIF como sea posible. La búsqueda de metadatos u otras propiedades descriptivas no está en el ámbito de esta especificación.

Para facilitar la búsqueda de contenido desconocido, se especifica también un servicio relacionado de autocompletamiento de términos. El servicio autocompletar es específico de un servicio de búsqueda para garantizar que los términos recuperados se puedan copiar en la consulta de la búsqueda.

Por favor, envíe sus comentarios a iiif-discuss@googlegroups.com

1.1. Casos de Uso

Los casos de uso de la búsqueda de anotaciones de la API de Presentación incluyen:

  • Buscar en texto generado por OCR para encontrar palabras o frases en un libro, periódico, u otro contenido textual.
  • Buscar en contenido transcrito, generado por crowd-sourcing o transformación de la producción académica.
  • Buscar en múltiples contenidos, por ejemplo, la traducción o edición, en lugar de la transcripción no procesada, para saltar a la parte apropiada de un objeto.
  • Buscar en secciones del texto, como capítulos o artículos definidos.
  • Buscar en los comentarios de los usuarios sobre el recurso, ya sea como mecanismo de descubrimiento del recurso, o para la discusión.
  • Descubrir secciones similares del texto para comparar el contenido o el objeto.

Las interfaces de usuario que se pueden construir a partir de la respuesta a la búsqueda incluyen el resalte de las palabras coincidentes en la pantalla, un mapa térmico de la ubicación de las coincidencias en el objeto, y un mecanismo para saltar de un punto a otro en el objeto. El servicio autocompletar ayuda a los usuarios a identificar los términos que existen en el ámbito seleccionado.

1.2. Terminología

En este documento, las palabras resaltadas debe(n) y requerido(a) implican que la definición es un requisito absoluto de la especificación; la expresión no debe(n) implica que la definición es una prohibición absoluta de la especificación; las palabras debiera(n) y recomendado(a) implican que pueden existir razones válidas en circunstancias particulares para ignorar un elemento particular, pero es preciso comprender y sopesar cuidadosamente todas las consecuencias antes de seguir un curso diferente; las expresiones no debiera(n) o no recomendado(a) implican que pueden existir razones válidas en circunstancias particulares donde el comportamiento particular es aceptable o útil, pero es preciso comprender y sopesar cuidadosamente todas las consecuencias antes de implementarlo; las palabras puede(n) y opcional implican que el elemento de la especificación es verdaderamente opcional, si bien la implementación que no incluya una opción particular debe estar preparada para interoperar con otra implementación que sí la incluya (aunque quizás con funcionalidad reducida) e, inversamente, una implementación que incluya una opción particular debe estar preparada para interoperar con otra implementación que no la incluya (excepto, por supuesto, para la característica proporcionada por la opción).

Adaptación de la parte relevante del documento referenciado (RFC 2119) por la versión original de esta sección.

2. Reseña

La API de Presentación de IIIF ofrece información suficiente para que un visor pueda presentar imágenes y otros contenidos al usuario en una forma enriquecida y comprensible. Esos recursos de contenido pueden estar asociados a anotaciones textuales, y las anotaciones pueden estar asociadas a los componentes estructurales de la API de Presentación, por ejemplo, manifest, sequence, range, y layer. Además, las anotaciones pueden ser respondidas por otras anotaciones para formar una discusión en hilos sobre el comentario, transcripción, edición, o traducción.

Típicamente, las aplicaciones de visualización reciben las anotaciones en una lista de anotaciones (AnnotationList), donde todas las anotaciones apuntan al mismo recurso, o parte del recurso. Esas listas se pueden referenciar directamente desde el documento manifest para permitir que los clientes las recuperen siguiendo el enlace. Para contenido fijo, curado, ese método de descubrimiento es apropiado, pues las anotaciones no cambian con frecuencia, ni es probable que se distribuyan entre varios sevidores. Las listas de anotaciones se pueden agrupar en recursos layer (por ejemplo, según el origen de las anotaciones) para permitir al usuario manipular esos grupos como un todo.

Sin embargo, eso es menos útil para anotaciones de comentario, transcripciones por crowd-sourcing o distribuídas, correcciones de transcripciones OCR automatizadas, y similares, ya que el flujo de las anotaciones puede ser constante. Además, la capacidad de descubrir rápidamente las anotaciones individuales, sin recorrer todas las vistas de un objeto, es esencial para una experiencia de usuario razonable. Esta especificación suma esa capacidad a la suite de especificaciones de IIIF.

Fuera de la posibilidad de buscar palabras o frases, es útil ofrecer a los usuarios sugerencias de los términos que pueden buscar. Esa facilidad se suele llamar autocompletar o type-ahead, y en el contexto de un objeto puede proporcionar información sobre el idioma y el contenido. El servicio autocompletar se asocia a un servicio de búsqueda en el cual se pueden introducir los términos como parte de una consulta.

El servicio de búsqueda recibe una consulta, que incluye típicamente un término de búsqueda o URI, y puede estar filtrada por otras propiedades, incluyendo la fecha de creación o última modificación de la anotación, la motivación (motivation) de la anotación, o el usuario que creó la anotación.

3.1. Descripción del Servicio

Todo recurso de la API de Presentación puede ser asociado a un servicio de búsqueda. El recurso establece el ámbito del contenido que se buscará. Un servicio asociado a un manifest busca todas las anotaciones en recursos canvas u otros objetos del manifest; un servicio asociado a un range particular busca sólo en los recursos canvas del range; y un servicio asociado a un canvas busca sólo las anotaciones de ese canvas particular.

La descripción del servicio cumple el patrón establecido en la especificación Enlazando con Servicios. El bloque de descripción debe incluir la propiedad @context con el valor “http://iiif.io/api/search/1/context.json”, la propiedad profile con el valor “http://iiif.io/api/search/1/search”, y la propiedad @id, que contiene la URI donde se puede efectuar la búsqueda.

Un ejemplo de bloque de descripción del servicio:

{
  // ... recurso a que está asociado el servicio de búsqueda ...
  "service": {
    "@context": "http://iiif.io/api/search/1/context.json",
    "@id": "http://example.org/services/identifier/search",
    "profile": "http://iiif.io/api/search/1/search"
  }
}

3.2. Petición

La petición de búsqueda se hace a un servicio relacionado a un recurso particular de la API de Presentación. Las URIs de servicios asociados a distintos recursos deben ser distintas para permitir al cliente seleccionar la correcta para el ámbito de búsqueda deseado. Para efectuar una búsqueda, el cliente debe usar GET (no POST) HTTP para hacer la petición al servicio, y parámetros de consulta para especificar los términos de búsqueda.

3.2.1. Parámetros de Consulta

Salvo q, que es recomendado, la presencia de otro parámetro en la petición es opcional. El comportamiento predeterminado, ante un parámetro vacío o no suministrado, es no restringir por ese parámetro las anotaciones encontradas por la búsqueda. Si se indica un valor pero el campo no está presente en la anotación, la búsqueda no coincide con esa anotación. Por ejemplo, si una anotación carece de creador, y la consulta especifica el parámetro user, la anotación no coincide con la consulta.

Los servidores debieran implementar los parámetros q y motivation, y pueden implementar los otros parámetros. Los parámetros recibidos en una petición que no estén implementados se deben ignorar, y se debieran incluir en la propiedad ignored del layer en la respuesta, descrito más adelante.

Parámetro Definición
q Lista separada por espacios de los términos de búsqueda. Los términos de búsqueda pueden ser palabras (para buscar en textos) o URIs (para buscar identidades de recursos annotation). La semántica de múltiples términos separados por espacios depende de la implementación del servidor.
motivation Lista separada por espacios de los términos de motivación. Si se especifican varias motivaciones, una anotación coincide con la búsqueda si alguna de las motivaciones está presente. Los valores esperados están en la tabla siguiente.
date Lista separada por espacios de rangos de fecha. Una anotación coincide si su fecha de creación pertenece a alguno de los rangos de fecha suministrados. Las fechas deben estar en el formato ISO8601: AAAA-MM-DDThh:mm:ssZ/AAAA-MM-DDThh:mm:ssZ. Las fechas se deben expresar en UTC y deben estar en el formato basado en Z.
user Lista separada por espacios de URIs que son identidades de usuarios. Si se especifican varios usuarios, una anotación coincide con la búsqueda si fue creada por alguno de esos usuarios.

Los valores comunes del parámetro motivation:

Motivación Definición
painting Anotaciones con motivation sc:painting
non-painting Anotaciones con motivation distinta de sc:painting
commenting Anotaciones con motivation oa:commenting
describing Anotaciones con motivation oa:describing
tagging Anotaciones con motivation oa:tagging
linking Anotaciones con motivation oa:linking

Otras motivaciones son posibles, y la lista completa de la especificación Open Annotation debiera estar disponible descartando el prefijo “oa:”. Las motivaciones específicas de comunidades debieran incluir un prefijo, o usar sus URIs completas.

3.2.2. Ejemplo de Petición

Este ejemplo de petición:

http://example.org/services/manifest/search?q=bird&motivation=painting

Buscaría anotaciones de motivación painting, y con la palabra “bird” en sus textos, en el recurso asociado al servicio.

3.3. Respuestas Compatibles con la API de Presentación

La respuesta del servidor es una lista de anotaciones, siguiendo el formato de la API de Presentación, con algunas características adicionales. De esa manera, los clientes que implementan el formato AnnotationList no requieren trabajo adicional para soportar resultados de búsqueda.

Los resultados de búsqueda se retornan como anotaciones en la sintaxis normal de IIIF. Note que las anotaciones pueden proceder de múltiples recursos canvas, mientras que en la situación predeterminada de la API de Presentación todas las anotaciones apuntan al mismo canvas.

3.3.1. Listas Simples

La respuesta más simple es una lista de anotaciones común, que retorna todas las anotaciones coincidentes en una sola respuesta. El valor de @id es igual a la URI de la consulta, pero los servidores pueden descartar parámetros de consulta ignorados siempre que los reporten en la propiedad ignored.

Para conocer la cantidad total de anotaciones coincidentes, los clientes pueden contar el número de anotaciones en la propiedad resources, pues todas las coincidencias fueron retornadas. La descripción completa de la anotación se debe incluir en la respuesta, aunque las anotaciones se pueden desreferenciar por separado mediante sus URIs.

{
  "@context":"http://iiif.io/api/presentation/2/context.json",
  "@id":"http://example.org/service/manifest/search?q=bird&motivation=painting",
  "@type":"sc:AnnotationList",

  "resources": [
    {
      "@id": "http://example.org/identifier/annotation/anno-line",
      "@type": "oa:Annotation",
      "motivation": "sc:painting",
      "resource": {
        "@type": "cnt:ContentAsText",
        "chars": "A bird in the hand is worth two in the bush"
      },
      "on": "http://example.org/identifier/canvas1#xywh=100,100,250,20"
    }
    // Más anotaciones coincidentes aquí ...
  ]
}

3.3.2. Paginación de los Resultados

Para grandes listas de anotaciones, el servidor puede dividir la respuesta en secciones, que se suelen llamar páginas. Cada página es una lista de anotaciones, y puede referenciar a otras páginas para que el cliente pueda recorrer el conjunto completo. Eso utiliza las características de paginación introducidas en la versión 2.1 de la API de Presentación, pero es compatible hacia atrás con la versión 2.0. La página de resultados que sigue a la actual se debe referenciar en una propiedad next de la lista de anotaciones, y la página anterior se debiera referenciar en una propiedad prev.

La URI de la primera lista de anotaciones reportada en la propiedad @id puede ser distinta de la usada por el cliente para solicitar la búsqueda. Cada página debiera tener una propiedad startIndex cuyo valor entero reporta la posición de su primer resultado en el conjunto total de los resultados (el índice de la primera anotación es 0). Por ejemplo, si el cliente solicita la primera página, que tiene 10 coincidencias, startIndex será 0, y startIndex de la segunda página será 10, por ser la coincidencia 11.

Todas las páginas están en un layer que representa el conjunto de todas las anotaciones coincidentes. El layer es el valor de la propiedad within de la lista de anotaciones de cada página, y se registra como un objeto con propiedades.

El layer debe tener la propiedad @type, con valor “sc:Layer”. debiera referenciar las URIs de las páginas (listas de anotaciones) inicial y final en las propiedades first y last, respectivamente. debiera tener la propiedad total, cuyo valor es la cantidad total de coincidencias generadas por la consulta, y puede tener una URI, que sería el valor de la propiedad @id.

Un ejemplo de petición:

http://example.org/service/manifest/search?q=bird

Y la primera página de anotaciones de una respuesta con 125 coincidencias:

{
  "@context":"http://iiif.io/api/presentation/2/context.json",
  "@id":"http://example.org/service/manifest/search?q=bird&page=1",
  "@type":"sc:AnnotationList",

  "within": {
    "@type": "sc:Layer",
    "total": 125,
    "first": "http://example.org/service/manifest/search?q=bird&page=1",
    "last": "http://example.org/service/identifier/search?q=bird&page=13"
  },
  "next": "http://example.org/service/identifier/search?q=bird&page=2",
  "startIndex": 0,

  "resources": [
    {
      "@id": "http://example.org/identifier/annotation/anno-line",
      "@type": "oa:Annotation",
      "motivation": "sc:painting",
      "resource": {
        "@type": "cnt:ContentAsText",
        "chars": "A bird in the hand is worth two in the bush"
      },
      "on": "http://example.org/identifier/canvas1#xywh=100,100,250,20"
    }
    // Más anotaciones de la primera página aquí ...
  ]
}

3.3.3. Estructura del Recurso Objetivo

Las anotaciones pueden incluir referencias a la estructura o estructuras a que pertenece el objetivo (el recurso en la propiedad on). Se deben proporcionar la URI y tipo del recurso contenedor, y se debiera incluir un label.

Esta estructura se indica explícitamente pues aunque usa propiedades de la API de Presentación, no es un patrón común, y los clientes pueden no esperarla.

{
  "@context":"http://iiif.io/api/search/1/context.json",
  "@id":"http://example.org/service/manifest/search?q=bird&motivation=painting",
  "@type":"sc:AnnotationList",

  "resources": [
    {
      "@id": "http://example.org/identifier/annotation/anno-line",
      "@type": "oa:Annotation",
      "motivation": "sc:painting",
      "resource": {
        "@type": "cnt:ContentAsText",
        "chars": "A bird in the hand is worth two in the bush"
      },
      "on": {
        "@id": "http://example.org/identifier/canvas1#xywh=100,100,250,20",
        "within": {
          "@id": "http://example.org/identifier/manifest",
          "type": "sc:Manifest",
          "label": "Ejemplo de Manifest"
        }
      }
    }
    // Más anotaciones aquí ...
  ]
}

3.4 Respuestas Específicas de la API de Búsqueda

Pueden existir propiedades específicas del resultado de búsqueda, no características de la anotación en general, que es útil retornar al cliente. Tales propiedades incluyen el texto anterior y posterior al contenido coincidente (para permitir la presentación de un recorte del resultado), el texto coincidente (si se aplicaron normalización, stemming o comodines), y una referencia al conjunto de anotaciones que satisfacen la consulta de búsqueda (si una frase abarca varias anotaciones).

Como esas repuestas incluyen información específica de la API de Búsqueda, el valor de @context debe ser un array con las URIs de contexto de la API de Presentación y la API de Búsqueda, en ese orden. Eso permite que las APIs se desarrollen por separado, pero permanezcan tan sincronizadas como sea posible.

Para construir incrementalmente sobre soluciones existentes, y ofrecer degradación elegante a los clientes que no soporten esas características, y retener la compatibilidad con la API de Presentación, la información específica de la API de Búsqueda se incluye en una segunda lista en la lista de anotaciones, llamada hits, distinta de la propiedad ignored del layer. Las listas de anotaciones pueden tener esa propiedad, y los servidores pueden soportar esas características.

Si es soportada, cada entrada de la lista hits es un objeto search:Hit. Ese tipo se debe incluir como valor de la propiedad @type. Los objetos hit referencian una o más anotaciones, de las cuales ofrecen información adicional, en una lista, como valor de la propiedad annotations del hit. Se referencia el valor de la propiedad @id de la anotación; por tanto, las anotaciones deben tener URIs para habilitar esta información adicional.

La estructura básica es:

{
  "@context":[
      "http://iiif.io/api/presentation/2/context.json",
      "http://iiif.io/api/search/1/context.json"
  ],
  "@id":"http://example.org/service/manifest/search?q=bird&page=1",
  "@type":"sc:AnnotationList",

  "within": {
    "@type": "sc:Layer"
    // Información del conjunto de resultados aquí ...
  },

  "resources": [
    {
      "@id": "http://example.org/identifier/annotation/anno1",
      "@type": "oa:Annotation"
      // Más información de anotaciones aquí ...
    }
    // Más anotaciones de la primera página aquí ...
  ],

  "hits": [
    {
      "@type": "search:Hit",
      "anotaciones": [
        "http://example.org/identifier/annotation/anno1"
      ]
      // Más información específica de la búsqueda para anno1 aquí ...
    }
    // Más hits para la primera página aquí ...
  ]
}

3.4.1. Parámetros Ignorados

Si el servidor ignora algún parámetro de la petición, el layer debe estar presente, y debe tener una propiedad ignored cuyo valor es una lista de los parámetros ignorados.

Si la petición es:

http://example.org/service/manifest/search?q=bird&user=http%3A%2F%2Fexample.com%2Fusers%2Fazaroth42

Y se ignora el parámetro user al procesar la petición, la respuesta será:

{
  "@context":[
      "http://iiif.io/api/presentation/2/context.json",
      "http://iiif.io/api/search/1/context.json"
  ],
  "@id":"http://example.org/service/manifest/search?q=bird&page=1",
  "@type":"sc:AnnotationList",

  "within": {
    "@type": "sc:Layer",
    "total": 125,
    "ignored": ["user"]
  },
  "next": "http://example.org/service/identifier/search?q=bird&page=2",
  "startIndex": 0,

  "resources": [
    // anotaciones ...
  ]
}

3.4.2. Recortes de Términos de Búsqueda

La adición más simple al objeto hit es añadir texto que aparezca antes y después del texto coincidente de la anotación, lo cual permite que el cliente construya un recorte donde el texto coincidente se ofrece en el contexto del contenido que lo rodea, no por sí solo. Eso es de gran utilidad si el servicio posee fronteras a nivel de palabra del texto en el canvas, por ejemplo, las resultantes de emplear Optical Character Recognition (OCR) para generar las posiciones de los textos.

El servicio puede añadir una propiedad before al hit, con cierta cantidad de texto que aparezca antes del contenido de la anotación (en chars), y puede añadir una propiedad after, con cierta cantidad de texto que aparezca después del contenido de la anotación.

Por ejemplo, en una búsqueda del término “bird” en nuestra oración de ejemplo, cuando el servidor posee coordenadas completas a nivel de palabra:

http://example.org/service/manifest/search?q=bird

Que el servidor encuentra en el plural “birds”:

{
  "@context":[
      "http://iiif.io/api/presentation/2/context.json",
      "http://iiif.io/api/search/1/context.json"
  ],
  "@id":"http://example.org/service/manifest/search?q=bird",
  "@type":"sc:AnnotationList",

  "resources": [
    {
      "@id": "http://example.org/identifier/annotation/anno-bird",
      "@type": "oa:Annotation",
      "motivation": "sc:painting",
      "resource": {
        "@type": "cnt:ContentAsText",
        "chars": "birds"
      },
      "on": "http://example.org/identifier/canvas1#xywh=200,100,40,20"
    }
    // Más anotaciones aquí ...
  ],

  "hits": [
    {
      "@type": "search:Hit",
      "anotaciones": [
        "http://example.org/identifier/annotation/anno-bird"
      ],
      "before": "There are two ",
      "after": " in the bush"
    }
    // Más hits para la primera página aquí ...
  ]
}

3.4.3. Resalte de Términos de Búsqueda

Muchos sistemas no poseen coordenadas completas a nivel de palabra, y están limitados a fronteras a nivel de línea o párrafo. En ese caso, lo más útil que el cliente puede hacer es mostrar toda la anotación, y resaltar los hits. Eso es similar, pero distinto, del caso de uso anterior. La palabra aparece en alguna parte de la propiedad chars de la anotación, y el cliente debe destacarla. En la situación anterior, la palabra era todo el contenido de la anotación, y la información era conveniente para presentar en una lista.

En este caso, el cliente debe conocer el texto que hizo que el servicio creara el hit, e información suficiente sobre su ubicación en el contenido para resaltarlo correctamente, sin destacar no-coincidencias. Para ese fin, el servicio puede suministrar texto anterior y posterior al término coincidente en el contenido de la anotación, mediante un objeto TextQuoteSelector de Open Annotation. Los objetos TextQuoteSelector tienen tres propiedades: exact para registrar el texto exacto a buscar, prefix para texto anterior a la coincidencia, y suffix para texto posterior a la coincidencia.

Sería así:

{
  "@type": "oa:TextQuoteSelector",
  "exact": "birds",
  "prefix": "There are two ",
  "suffix": " in the bush"
}

Como varias palabras pueden coincidir con la consulta en una misma anotación, es posible especificar múltiples selectores en el hit, como objetos en una propiedad selectors. Por ejemplo, al emplear un comodín para buscar todas las palabras que comienzan con “b”, la misma anotación sería encontrada dos veces:

http://example.org/service/manifest/search?q=b*

El resultado podría ser:

{
  "@context":[
      "http://iiif.io/api/presentation/2/context.json",
      "http://iiif.io/api/search/1/context.json"
  ],
  "@id":"http://example.org/service/manifest/search?q=b*&page=1",
  "@type":"sc:AnnotationList",

  "resources": [
    {
      "@id": "http://example.org/identifier/annotation/anno-line",
      "@type": "oa:Annotation",
      "motivation": "sc:painting",
      "resource": {
        "@type": "cnt:ContentAsText",
        "chars": "There are two birds in the bush."
      },
      "on": "http://example.org/identifier/canvas1#xywh=200,100,40,20"
    }
    // Más anotaciones aquí ...
  ],

  "hits": [
    {
      "@type": "search:Hit",
      "anotaciones": [
        "http://example.org/identifier/annotation/anno-line"
      ],
      "selectors": [
        {
          "@type": "oa:TextQuoteSelector",
          "exact": "birds",
          "prefix": "There are two ",
          "suffix": " in the bush"
        },
        {
          "@type": "oa:TextQuoteSelector",
          "exact": "bush",
          "prefix": "two birds in the ",
          "suffix": "."
        }        
      ]
    }
    // Más hits para la primera página aquí ...
  ]
}

3.4.4. Hits de Múltiples Anotaciones

Dada la flexibilidad de la alineación entre las secciones del texto (por ejemplo, palabra, línea, párrafo, página, o secciones arbitrarias), y las anotaciones que presentan ese texto al cliente, múltiples anotaciones pueden coincidir con una sola búsqueda de varios términos. Las diferencias dependen fundamentalmente del método usado para generar texto y anotaciones, y es probable que sean importantes para texto transcrito manualmente y texto generado por OCR.

Por ejemplo, suponga que las anotaciones están divididas por líneas, pues se transcribieron manualmente de esa manera, y hay dos líneas de texto. En este ejemplo, la primera línea es “A bird in the hand”, la segunda línea es “is worth two in the bush”, y la búsqueda es la frase “hand is”. Por tanto, la coincidencia abarca las dos anotaciones de línea. Si, en cambio, las anotaciones fueran a nivel de palabra, toda búsqueda de frase requeriría varias anotaciones.

En estos casos existen más anotaciones que hits pues se necesitan dos o más anotaciones para construir un hit. La propiedad match del hit contiene el texto coincidente.

{
  "@context":[
      "http://iiif.io/api/presentation/2/context.json",
      "http://iiif.io/api/search/1/context.json"
  ],
  "@id":"http://example.org/service/manifest/search?q=hand+is",
  "@type":"sc:AnnotationList",

  "resources": [
    {
      "@id": "http://example.org/identifier/annotation/anno-bird",
      "@type": "oa:Annotation",
      "motivation": "sc:painting",
      "resource": {
        "@type": "cnt:ContentAsText",
        "chars": "A bird in the hand"
      },
      "on": "http://example.org/identifier/canvas1#xywh=200,100,150,30"
    },
    {
      "@id": "http://example.org/identifier/annotation/anno-are",
      "@type": "oa:Annotation",
      "motivation": "sc:painting",
      "resource": {
        "@type": "cnt:ContentAsText",
        "chars": "is worth two in the bush"
      },
      "on": "http://example.org/identifier/canvas1#xywh=200,140,170,30"
    }
    // Más anotaciones aquí ...
  ],

  "hits": [
    {
      "@type": "search:Hit",
      "anotaciones": [
        "http://example.org/identifier/annotation/anno-bush",
        "http://example.org/identifier/annotation/anno-are"
      ],
      "match": "hand is",
      "before": "A bird in the ",
      "after": " worth two in the bush"
    }
    // Más hits para la primera página aquí ...
  ]
}

4. Autocompletar

El servicio autocompletar retorna términos que es posible añadir al parámetro q del servicio de búsqueda relacionado, dados los primeros caracteres de un término.

4.1. Descripción del Servicio

El servicio autocompletar se anida en el servicio de búsqueda al que proporciona completamiento de términos. Eso permite múltiples servicios de búsqueda, cada cual con un servicio autocompletar propio.

El servicio autocompletar debe tener una propiedad @id cuyo valor es la URI donde se puede interactuar con el servicio, y debe tener una propiedad profile con valor “http://iiif.io/api/search/1/autocomplete” para distinguirlo de otros servicios.

{
  // Recurso al cual están asociados los servicios ...
  "service": {
    "@context": "http://iiif.io/api/search/1/context.json",
    "@id": "http://example.org/services/identifier/search",
    "profile": "http://iiif.io/api/search/1/search",
    "service": {
      "@id": "http://example.org/services/identifier/autocomplete",
      "profile": "http://iiif.io/api/search/1/autocomplete"
    }
  }
}

4.2. Petición

La petición es muy similar a la petición de búsqueda, con un parámetro adicional para restringir el número de veces que aparece el término en el objeto. El valor del parámetro q, que es requerido en el servicio autocompletar, son los caracteres iniciales del término que debe completar el servicio. Por ejemplo, el término de consulta ‘bir’ se podría completar como ‘bird’, ‘biro’, ‘birth’, y ‘birthday’.

El término se debiera parsear como un string completo, aunque incluya espacio en blanco. Por ejemplo, el término de consulta “green bir” no debiera autocompletar en campos que coincidan con “green”, e incluir también lo que empiece con “bir”, sino buscar términos que comiencen con el string “green bir”.

Los otros parámetros (motivation, date y user), si son soportados, refinan el conjunto de términos de la respuesta a sólo los que proceden de anotaciones que coinciden con esos filtros. Por ejemplo, si la motivación es “painting”, sólo el texto de las transcripciones de pintura contribuye a la lista de términos de la respuesta.

4.2.1. Parámetros de Consulta

Parámetro Definición
min Cantidad mínima de veces que debe aparecer un término en el índice para ser incluído en la respuesta; si no se especifica, su valor es 1. Soportar este parámetro es opcional

4.2.2. Ejemplo de Petición

Un ejemplo de petición

http://example.org/service/identifier/autocomplete?q=bir&motivation=painting&user=http%3A%2F%2Fexample.com%2Fusers%2Fazaroth42

4.3. Respuesta

La respuesta es una lista (una “search:TermList”) de objetos simples que incluyen el término, el enlace de la búsqueda de ese término, y el número de coincidencias de esa búsqueda. El servidor determina la cantidad de términos de la lista.

Los parámetros no procesados por el servicio se deben retornar en la propiedad ignored del objeto “TermList”. El valor debe ser un array de strings.

Los objetos de la lista de términos tienen todos el @type “search:Term”, lo cual se puede indicar explícitamente, pero no es necesario. El objeto Term tiene varias propiedades:

  • El término coincidente es el valor de la propiedad match, y debe estar presente.
  • El enlace de la búsqueda del término coincidente es el valor de la propiedad url, y debe estar presente.
  • El número de coincidencias del término es el valor entero de la propiedad count, y debiera estar presente.
  • El valor de la propiedad label es un label para mostrar en lugar de la coincidencia, y puede estar presente. Puede haber más de un label, para permitir la internacionalización.

Los términos se debieran proporcionar en orden alfabético ascendente, pero se admiten otros órdenes, por ejemplo, descendiente por count del término, para situar al principio las coincidencias más comunes.

El ejemplo de petición anterior podría generar esta respuesta:

{
  "@context": "http://iiif.io/api/search/1/context.json",
  "@id": "http://example.org/service/identifier/autocomplete?q=bir&motivation=painting",
  "@type": "search:TermList",
  "ignored": ["user"],
  "terms": [
    {
      "match": "bird",
      "url": "http://example.org/service/identifier/search?motivation=painting&q=bird",
      "count": 15
    },
    {
      "match": "biro",
      "url": "http://example.org/service/identifier/search?motivation=painting&q=biro",
      "count": 3
    },
    {
      "match": "birth",
      "url": "http://example.org/service/identifier/search?motivation=painting&q=birth",
      "count": 9
    },
    {
      "match": "birthday",
      "url": "http://example.org/service/identifier/search?motivation=painting&q=birthday",
      "count": 21
    }
  ]
}

También es posible asociar uno o más labels que mostrar al usuario con URIs u otros datos que se puedan buscar mediante el parámetro q, en lugar de usar el string exacto de la coincidencia. Eso permite mostrar el original, no el término procesado, cuando se aplicó stemming u otra normalización de términos.

{
  "@context": "http://iiif.io/api/search/1/context.json",
  "@id": "http://example.org/service/identifier/autocomplete?q=http%3A%2F%2Fsemtag.example.org%2Ftag%2Fb&motivation=tagging",
  "ignored": ["user"],
  "terms": [
    {
      "match": "http://semtag.example.org/tag/bird",
      "url": "http://example.org/service/identifier/autocomplete?motivation=tagging&q=http%3A%2F%2Fsemtag.example.org%2Ftag%2Fbird",
      "count": 15,
      "label": "bird"
    },
    {
      "match": "http://semtag.example.org/tag/biro",
      "url": "http://example.org/service/identifier/autocomplete?motivation=tagging&q=http%3A%2F%2Fsemtag.example.org%2Ftag%2Fbiro",
      "count": 3,
      "label": "biro"
    }
  ]
}

5. Definiciones de Propiedades

after
Segmento de texto que aparece después del texto que hizo que la anotación particular coincidiera con la búsqueda. El valor debe ser un solo string.
  • Hit puede tener la propiedad after.
before
Segmento de texto que aparece antes del texto que hizo que la anotación particular coincidiera con la búsqueda. El valor debe ser un solo string.
  • Hit puede tener la propiedad before.
count
Cantidad de veces que aparece el término. El valor debe ser un entero positivo.
  • Term debiera tener la propiedad count.
ignored
Conjunto de los parámetros que el servidor recibió, pero no tomó en cuenta al procesar la consulta. El valor debe ser un array de strings.
  • TermList y Layer pueden tener la propiedad ignored, y deben tenerla si el servidor ignoró algún parámetro de consulta.
match
Texto que hizo que la anotación particular coincidiera con la búsqueda. El valor debe ser un solo string.
  • Hit puede tener la propiedad match.
  • Term debe tener la propiedad match.

Apéndices

A. Requisitos de los Parámetros de Petición

Parámetro Requerido en la Petición Requerido en Búsqueda Requerido en Autocompletar
q recomendado recomendado obligatorio
motivation opcional recomendado opcional
date opcional opcional opcional
uri opcional opcional opcional
min opcional n/a opcional

B. Control de Versiones

Esta especificación sigue Semantic Versioning. Vea la nota Control de Versiones de APIs para los detalles de implementación.

C. Agradecimientos

La producción de este documento fue apoyada generosamente por una donación de la Fundación Andrew W. Mellon.

Muchas gracias a los miembros de IIIF por su continuo compromiso, ideas innovadoras y retroalimentación.

D. Registro de Cambios

Fecha
Descripción
2016-05-12 Versión 1.0 (Lost Summer)
2015-07-20 Versión 0.9 (Trip Life)